/*
* Copyright (c) 2025 Shenzhen Kaihong Digital Industry Development Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef OHMW_FRAMEWORK_CXX_BINCODE_ENCODER_H
#define OHMW_FRAMEWORK_CXX_BINCODE_ENCODER_H

#include <cstddef>
#include <cstdint>
#include <string>
#include <string_view>
#include <vector>
#include "Endian.h"

namespace OHOS {
namespace OHMW {
class Encoder {
public:
    virtual ~Encoder() {}

    virtual bool Put(std::vector<uint8_t> &buffer, bool value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, char value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, uint8_t value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, uint16_t value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, uint32_t value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, uint64_t value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, int8_t value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, int16_t value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, int32_t value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, int64_t value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, float value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, double value) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, const uint8_t* bytes, size_t len) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, std::string_view s) = 0;
    virtual bool Put(std::vector<uint8_t> &buffer, const std::string &s) = 0;

    virtual void PutUnchecked(std::vector<uint8_t> &buffer, bool value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, char value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, uint8_t value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, uint16_t value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, uint32_t value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, uint64_t value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, int8_t value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, int16_t value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, int32_t value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, int64_t value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, float value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, double value) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, const uint8_t* bytes, size_t len) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, std::string_view s) = 0;
    virtual void PutUnchecked(std::vector<uint8_t> &buffer, const std::string &s) = 0;
};

class DefaultEncoder : public Encoder {
public:
    DefaultEncoder() = default;
    DefaultEncoder(size_t offset) : offset_(offset) {}
    DefaultEncoder(const DefaultEncoder&) = default;
    DefaultEncoder& operator=(const DefaultEncoder&) = default;
    DefaultEncoder(DefaultEncoder&&) = default;
    DefaultEncoder& operator=(DefaultEncoder&&) = default;
    ~DefaultEncoder() override = default;

    bool Put(std::vector<uint8_t> &buffer, bool value) override {
        return Put(buffer, static_cast<uint8_t>(value));
    }

    bool Put(std::vector<uint8_t> &buffer, char value) override {
        return Put(buffer, static_cast<uint8_t>(value));
    }

    bool Put(std::vector<uint8_t> &buffer, uint8_t value) override {
        if (offset_ + 1 > buffer.size()) {
            buffer.resize(offset_ + 1);
        }
        buffer[offset_++] = value;
        return true;
    }

    bool Put(std::vector<uint8_t> &buffer, uint16_t value) override {
        value = host2le(value);
        return Put(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(uint16_t));
    }

    bool Put(std::vector<uint8_t> &buffer, uint32_t value) override {
        value = host2le(value);
        return Put(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(uint32_t));
    }

    bool Put(std::vector<uint8_t> &buffer, uint64_t value) override {
        value = host2le(value);
        return Put(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(uint64_t));
    }

    bool Put(std::vector<uint8_t> &buffer, int8_t value) override {
        return Put(buffer, static_cast<uint8_t>(value));
    }

    bool Put(std::vector<uint8_t> &buffer, int16_t value) override {
        value = host2le(value);
        return Put(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(int16_t));
    }

    bool Put(std::vector<uint8_t> &buffer, int32_t value) override {
        value = host2le(value);
        return Put(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(int32_t));
    }

    bool Put(std::vector<uint8_t> &buffer, int64_t value) override {
        value = host2le(value);
        return Put(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(int64_t));
    }

    bool Put(std::vector<uint8_t> &buffer, float value) override {
        value = host2le(value);
        return Put(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(float));
    }

    bool Put(std::vector<uint8_t> &buffer, double value) override {
        value = host2le(value);
        return Put(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(double));
    }

    bool Put(std::vector<uint8_t> &buffer, const uint8_t* bytes, size_t len) override {
        if (offset_ + len > buffer.size()) {
            buffer.resize(offset_ + len);
        }
        PutUnchecked(buffer, bytes, len);
        return true;
    }

    bool Put(std::vector<uint8_t> &buffer, std::string_view s) override {
        uint32_t len = static_cast<uint32_t>(s.size());
        Put(buffer, len);
        return Put(buffer, reinterpret_cast<const uint8_t*>(s.data()), s.size());
    }

    bool Put(std::vector<uint8_t> &buffer, const std::string &s) override {
        uint32_t len = static_cast<uint32_t>(s.size());
        Put(buffer, len);
        return Put(buffer, reinterpret_cast<const uint8_t*>(s.data()), s.size());
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, bool value) override {
        PutUnchecked(buffer, static_cast<uint8_t>(value));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, char value) override {
        PutUnchecked(buffer, static_cast<uint8_t>(value));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, uint8_t value) override {
        buffer[offset_] = value;
        offset_ += 1;
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, uint16_t value) override {
        value = host2le(value);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(uint16_t));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, uint32_t value) override {
        value = host2le(value);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(uint32_t));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, uint64_t value) override {
        value = host2le(value);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(uint64_t));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, int8_t value) override {
        PutUnchecked(buffer, static_cast<uint8_t>(value));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, int16_t value) override {
        value = host2le(value);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(int16_t));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, int32_t value) override {
        value = host2le(value);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(int32_t));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, int64_t value) override {
        value = host2le(value);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(int64_t));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, float value) override {
        value = host2le(value);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(float));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, double value) override {
        value = host2le(value);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(&value), sizeof(double));
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, const uint8_t* bytes, size_t len) override {
        __builtin_memcpy(buffer.data() + offset_ , bytes, len);
        offset_ += len;
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, std::string_view s) override {
        uint32_t len = static_cast<uint32_t>(s.size());
        PutUnchecked(buffer, len);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(s.data()), s.size());
    }

    void PutUnchecked(std::vector<uint8_t> &buffer, const std::string &s) override {
        uint32_t len = static_cast<uint32_t>(s.size());
        PutUnchecked(buffer, len);
        PutUnchecked(buffer, reinterpret_cast<const uint8_t*>(s.data()), s.size());
    }

private:
    size_t offset_ = 0;
};
}
}

#endif
